﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Reflection;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration;
using Business.exception;


namespace Business.ibatis
{
    /// <summary>
    /// This class IBatis Mapper which retrieves a desired
    /// ibatis mapper for a certain database.
    /// </summary>
    public class IBatisMapper
    {
        // cache for ibatis mapper
        private static IDictionary<object, object> mapperPathAndNameCache = new Dictionary<object, object>();

        /// <summary>
        /// Private constructor
        /// </summary>
        private IBatisMapper()
        {
        }

        /// <summary>
        /// Clean the mapper instance
        /// </summary>
        /// <param name="obj">N/A</param>
        private static void configure(object obj)
        {
        }

        /// <summary>
        /// Initialize the iBatis.NET Data Mapper
        /// </summary>
        private static ISqlMapper InitMapper(String mapperPathAndName)
        {
            ISqlMapper mapper = null;

            // initialize ibatis mapper
            DomSqlMapBuilder builder = new DomSqlMapBuilder();
            // get a reference to the current assembly
            Assembly assembly = Assembly.GetExecutingAssembly();
            mapper = builder.Configure(assembly.GetManifestResourceStream(mapperPathAndName));

            return mapper;
        }

        /// <summary>
        /// Get the unique instance of the mapper
        /// </summary>
        /// <returns>SQL Mapper</returns>
        private static ISqlMapper CreateSingleton(String mapperPathAndName)
        {
            ISqlMapper mapper = null;

            mapper = InitMapper(mapperPathAndName);

            return mapper;
        }

        /// <summary>
        /// Get mapper path and file name according the given ibatis mapper type
        /// </summary>
        /// <returns>SQL Mapper</returns>
        public static ISqlMapper GetMapper()
        {
            ISqlMapper sqlMapper = null;
            String mapperPathAndName = null;

            try
            {
                //Lock the mapper cache
                lock (mapperPathAndNameCache)
                {

                    // in case there is no mapper in the cache, create and add one
                    if (mapperPathAndNameCache.Count == 0 || !mapperPathAndNameCache.ContainsKey("ibatisMapperType"))
                    {
                        // create mapper
                        mapperPathAndName = "Business.ibatis.config.SqlMap.config";
                        sqlMapper = CreateSingleton(mapperPathAndName);
                        // add it to the cache
                        mapperPathAndNameCache["ibatisMapperType"] = sqlMapper;
                    }
                    // get mapper from the cache
                    sqlMapper = (SqlMapper)mapperPathAndNameCache["ibatisMapperType"];

                }
            }
            catch (System.Exception ex)
            {
                // throw exception due to an unexpected error
                throw new WebSiteException("An unexpected error has occured while retrieving the IBatis implementation.", ex);
            }
            return sqlMapper;

        }
    }
}



